package com.example.demo.controller;

import com.example.demo.entity.Rule;
import com.example.demo.service.RuleService;
import com.example.demo.controller.vo.ResponseResult;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;
import java.util.HashMap;

@Slf4j
@RestController
@RequestMapping("/admin/rule")
public class RuleController {

    @Autowired
    private RuleService ruleService;

    @PostMapping
    public ResponseResult<Rule> createRule(@Validated @ModelAttribute Rule rule) {
        log.info("Creating new rule: name={}, menu={}", rule.getName(), rule.getMenu());
        Rule createdRule = ruleService.createRule(rule);
        if (createdRule == null) {
            throw new IllegalArgumentException("createdRule cannot be null");
        }
        
        if (createdRule.getId() <= 0) {
            throw new IllegalArgumentException("createdRule ID must be greater than 0");
        }
        log.info("Rule created successfully: id={}", createdRule.getId());
        return ResponseResult.success(createdRule);
    }

    @PostMapping("/{id}")
    public ResponseResult<Boolean> updateRule(@PathVariable Integer id, @Validated @ModelAttribute Rule rule) {
        log.info("Updating rule: id={}, name={}, menu={}", id, rule.getName(), rule.getMenu());
        rule.setId(id);
        boolean success = ruleService.updateRule(rule);
        if (success) {
            log.info("Rule updated successfully: id={}", id);
        } else {
            log.warn("Failed to update rule: id={}", id);
        }
        return ResponseResult.success(success);
    }

    @PostMapping("/{id}/delete")
    public ResponseResult<Boolean> deleteRule(@PathVariable Integer id) {
        log.info("Deleting rule: id={}", id);
        boolean success = ruleService.deleteRule(id);
        if (success) {
            log.info("Rule deleted successfully: id={}", id);
        } else {
            log.warn("Failed to delete rule: id={}", id);
        }
        return ResponseResult.success(success);
    }

    @GetMapping("/{page}")
    public ResponseResult<?> getRuleList(
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer size) {
        log.info("Fetching rule list: page={}, size={}", page, size);
        PageInfo<Rule> pageInfo = ruleService.getRuleList(page, size);
        log.debug("Fetched {} rules", pageInfo.getList().size());
        return ResponseResult.success(pageInfo);
    }

    @PostMapping("/{id}/update_status")
    public ResponseResult<Boolean> updateRuleStatus(
            @PathVariable Integer id,
            @RequestParam Integer status) {
        log.info("Updating rule status: id={}, new_status={}", id, status);
        boolean success = ruleService.updateRuleStatus(id, status);
        if (success) {
            log.info("Rule status updated successfully: id={}", id);
        } else {
            log.warn("Failed to update rule status: id={}", id);
        }
        return ResponseResult.success(success);
    }

    @GetMapping("/tree")
    public ResponseResult<?> getRuleTree() {
        log.info("Fetching rule tree");
        List<Rule> list = ruleService.getRuleTree(null);
        List<Rule> rules = ruleService.getRuleTree(1);
        
        // Sort rules and their children
        sortRules(list);
        sortRules(rules);
        
        // Create response structure
        Map<String, Object> responseData = new HashMap<>();
        responseData.put("list", list);
        responseData.put("rules", rules);
        
        return ResponseResult.success(responseData);
    }

    private void sortRules(List<Rule> rules) {
        if (rules == null || rules.isEmpty()) {
            return;
        }
        
        // Sort rules by rule_id and order
        rules.sort((r1, r2) -> {
            int idCompare = Integer.compare(r1.getRule_id(), r2.getRule_id());
            if (idCompare != 0) {
                return idCompare;
            }
            return Integer.compare(r1.getOrder(), r2.getOrder());
        });
        
        // Recursively sort children
        for (Rule rule : rules) {
            if (rule.getChild() != null && !rule.getChild().isEmpty()) {
                sortRules(rule.getChild());
            }
        }
    }
}
